package com.rs.game.player;

import java.io.Serializable;

import com.rs.Settings;
import com.rs.game.item.Item;
import com.rs.game.item.ItemsContainer;

public final class Bank implements Serializable {

	private static final long serialVersionUID = 1551246756081236625L;
	
	private transient Player player;
	private transient boolean withdrawNotes;
	private transient boolean insertItems;
	private transient int viewingTab;
	private transient long lastUse;
	/*private transient int item_X_Slot;
	private transient boolean withdrawX_Slot;*/
	private ItemsContainer<Item> bank;
	private short[] tabSeperatorIndex;
	@SuppressWarnings("unused")
	private short bankPin; //TODO
	
	public Bank() {
		bank = new ItemsContainer<Item>(496, true);
		tabSeperatorIndex = new short[10];
	}
	
	public void setPlayer(Player player) {
		this.player = player;
	}
	
	public void initSetPin() { //TODO
		
	}
	
	public void initBank() {
		player.getPackets().sendConfig(563, 4194304);
		player.getPackets().sendConfig(1248, -2013265920);
		player.getInterfaceManager().sendInterface(762);
		player.getInterfaceManager().sendInventoryInterface(763);
		viewingTab = 8; //default
		//item_X_Slot = -1;
		player.getTemporaryAttributtes().remove("bank_item_X_Slot");
		tabSeperatorIndex[9] = /*496; //*/(short) (bank.getSize() - getFreeSlots());
		sendInterItems();
		unlockButtons();
		sendTabLengths();
		refreshFreeSlots();
		sendBankName();
	}
	
	public void sendBankName() {
		player.getPackets().sendIComponentText(762, 32, "Bank Of "+Settings.SERVER_NAME);
	}
	
	public void unlockButtons() {
		//unlock bank inter all options
		player.getPackets().sendUnlockIComponentOptionSlots(762, 81, 0, 496, 0,1,2,3,4, 5,6);
		//unlock bank inv all options
		player.getPackets().sendUnlockIComponentOptionSlots(763, 0, 0, 27, 0,1,2,3,4,5);
		//dunno
		player.getPackets().sendRunScript(1451);
	}
	
	public void setViewingTab(int viewingTab) {
		this.viewingTab = viewingTab;
	}
	
	public void switchWithdrawNotes() {
		withdrawNotes = !withdrawNotes;
	}
	
	public void switchInsertItems() {
		insertItems = !insertItems;
		player.getPackets().sendConfig(305, insertItems ? 1 : 0);
	}
	
	public void sendInterItems() {
		player.getPackets().sendItems(-1, 0, 95, bank);
		lastUse = System.currentTimeMillis()+300;
	}
	
	
	public void sendTabLengths() {
		player.getPackets().sendConfig(1246, getTabLength(0) | getTabLength(1) << 10 | getTabLength(2) << 20);
		player.getPackets().sendConfig(1247, getTabLength(3) | getTabLength(4) << 10 | getTabLength(5) << 20);
		player.getPackets().sendConfig(1248, getTabLength(6) | getTabLength(7) << 10 | -2013265920);
	}
	
	public void refreshFreeSlots() {
		/*int usedSlots = bank.getUsedSlots();
		player.getPackets().sendIComponentText(762, 23, ""+(usedSlots > 68 ? 68 : usedSlots));
		player.getPackets().sendIComponentText(762, 25, ""+(usedSlots > 68 ? usedSlots-68 : 0));*/
		player.getPackets().sendIComponentText(762, 97, bank.getUsedSlots() + "");
	}
	
	public void withdrawLastAmount(int bankSlot) {
		Integer lastAmount = (Integer) player.getTemporaryAttributtes().get("bank_lastAmount");
		if(lastAmount == null)
			return;
		withdrawItem(bankSlot, lastAmount);
	}
	
	public void withdrawItemButOne(int bankSlot) {
		if(bankSlot < 0 || bankSlot > 495)
			return;
		Item item = bank.get(bankSlot);
		if(item == null)
			return;
		if(item.getAmount() <= 1) {
			player.getPackets().sendGameMessage("You only have one of this item in your bank");
			return;
		}
		withdrawItem(bankSlot, item.getAmount()-1);
	}
	
	public void withdrawItem(int bankSlot, int itemAmount) {
		if(lastUse > System.currentTimeMillis())
			return;
		if(itemAmount < 1 || bankSlot < 0 || bankSlot > 495)
			return;
		Item item = bank.get(bankSlot);
		if(item == null)
			return;
		Item[] itemsBefore  = player.getInventory().getItems().getItemsCopy();
		player.getTemporaryAttributtes().put("bank_lastAmount", itemAmount);
		if (itemAmount > item.getAmount())
			item = new Item(item.getId(), item.getAmount());
		else
			item = new Item(item.getId(), itemAmount);
		Item bankItem = new Item(item.getId(), item.getAmount());
		if(withdrawNotes) {
			if (!item.getDefinitions().isNoted() && item.getDefinitions().getCertId() != -1) {
				item.setId(item.getDefinitions().getCertId());
			}else{
				player.getPackets().sendGameMessage("You cannot withdraw this item as a note.");
			}
		}
		if((withdrawNotes || item.getDefinitions().isStackable())
				&& player.getInventory().getItems().containsOne(item)) {
			int slot = player.getInventory().getItems().getThisItemSlot(item);
			Item invItem = player.getInventory().getItems().get(slot);
			if (invItem == null)
				return;
			if (invItem.getId() != item.getId()) 
				return;
			if(invItem.getAmount() + item.getAmount() < 0) {
				player.getInventory().getItems().set(slot, new Item(item.getId(), Integer.MAX_VALUE));
				bank.add(new Item(bankItem.getId(), (int)((long)(invItem.getAmount() + item.getAmount()) - (long)(Integer.MAX_VALUE))));
				player.getPackets().sendGameMessage("Not enough space in your inventory.");
			}else
				player.getInventory().getItems().set(slot, new Item(item.getId(), invItem.getAmount() + item.getAmount()));
		}else{
			
			int freeSlots = player.getInventory().getFreeSlots();
			if (freeSlots <= 0) {
				player.getPackets().sendGameMessage("Not enough space in your inventory.");
				return;
			}
			if(item.getAmount() > freeSlots) {
				item = new Item(item.getId(), freeSlots);
				bankItem = new Item(bankItem.getId(), freeSlots);
			}
			player.getInventory().getItems().add(item);
		}
			int fromTab = getTabBySlot(bankSlot);
			bank.remove(bankItem);
			if(!bank.containsOne(bankItem))
				decreaseSeperators(fromTab);
			bank.shift();
			sendTabLengths();
			sendInterItems();
			player.getInventory().refreshItems(itemsBefore);
			refreshFreeSlots();
	}
	
	public void depositLastAmount(int bankSlot) {
		Integer lastAmount = (Integer) player.getTemporaryAttributtes().get("bank_lastAmount");
		if(lastAmount == null)
			return;
		depositItem(bankSlot, lastAmount);
	}
	
	public void depositItem(int invSlot, int itemAmount) {
		if(lastUse > System.currentTimeMillis())
			return;
		if(itemAmount < 1 || invSlot < 0 || invSlot > 27)
			return;
		Item item = player.getInventory().getItem(invSlot);
		if(item == null)
			return;
		int invAmountOf = player.getInventory().getItems().getNumberOf(item);
		if(invAmountOf < itemAmount) 
			item = new Item(item.getId(), invAmountOf);
		else
			item = new Item(item.getId(), itemAmount);
		Item invItem = new Item(item.getId(), item.getAmount());
		if (item.getDefinitions().isNoted() && item.getDefinitions().getCertId() != -1)
			item.setId(item.getDefinitions().getCertId());
		if(bank.containsOne(item)) {
			int slot = bank.getThisItemSlot(item);
			Item bankItem = bank.get(slot);
			if (bankItem == null)
				return;
			if (bankItem.getId() != item.getId())
				return;
			if(bankItem.getAmount() + item.getAmount() < 0) {
				bank.set(slot, new Item(item.getId(), Integer.MAX_VALUE));
				player.getInventory().addItem(invItem.getId(), (int)((long)(bankItem.getAmount() + item.getAmount()) - (long)(Integer.MAX_VALUE)));
				player.getPackets().sendGameMessage("Not enough space in your bank.");
			}else
				bank.set(slot, new Item(item.getId(), bankItem.getAmount() + item.getAmount()));
		}else {
			int slot = bank.freeSlot();
			if(slot == -1) {
				player.getPackets().sendGameMessage("Not enough space in your bank.");
				return;
			}
			increaseSeperators(viewingTab);//default tab, change to viewing tab
			bank.set(slot, new Item(item.getId(), item.getAmount()));
		}
		player.getInventory().deleteItem(invSlot, invItem);
		sendTabLengths();
		sendInterItems();
		player.getInventory().refresh();
		refreshFreeSlots();
	}
	
	public void depositAllInv() {
		if(lastUse > System.currentTimeMillis())
			return;
		for(int index = 0; index < 27; index++)
			depositItem(index, Integer.MAX_VALUE);
	}
	
	public void depositAllEquipment() {
		if(lastUse > System.currentTimeMillis())
			return;
		int slots = bank.freeSlots();
		if(slots < 16) {
			player.getPackets().sendGameMessage("Not enough space in your bank.");
			return;
		}
		player.getPackets().sendGameMessage("Still under construcion.");
	/*	bank.addAll(player.getEquipment().getItems());
		bank.shift();
		player.getEquipment().reset();
		player.getAppearence().generateAppearenceData();
		sendTabLengths();
		sendInterItems();
		refreshFreeSlots();*/
	}
	
	public int getTabLength(int tabId) {
		return tabSeperatorIndex[tabId + 1] - tabSeperatorIndex[tabId];
	}
	
	public int getTabBySlot(int slot) {
		int i = 0;
		while(slot >= tabSeperatorIndex[++i]);
		return i -1;
	}
	
	public int getFreeSlots() {
		return bank.getFreeSlots();
	}
	

	public void increaseSeperators(int startId) {
		for(int i = startId + 1; i < tabSeperatorIndex.length; i++) {
			tabSeperatorIndex[i]++;
		}
	}
	public void decreaseSeperators(int startId) {
		for(int i = startId + 1; i < tabSeperatorIndex.length; i++) {
			tabSeperatorIndex[i]--;
		}
		if(getTabLength(startId) == 0) {
			collapseTab(startId);
		}
	}

	public void collapseTab(int tabId) {
		int size = getTabLength(tabId);
		Item[] tempTabItems = new Item[size];
		for(int index = 0; index < size; index++) {
			tempTabItems[index] = bank.getItems()[tabSeperatorIndex[tabId] + index];
			bank.set(tabSeperatorIndex[tabId] + index, null);
		}
		bank.shift();
		for(int i = tabId; i < tabSeperatorIndex.length-1; i++) {
			tabSeperatorIndex[i] = (short) (tabSeperatorIndex[i+1] - size);
		}
		tabSeperatorIndex[8] -= size;
		for(int i = 0; i < size; i++) {
			bank.add(tempTabItems[i]);
		}
	}
	
}
